﻿using System;
using Neo4j.Driver;
using Newtonsoft.Json;
using JsonHelper;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;

namespace KG.Neo4j
{
    public class Neo4jRepository
    {

        private IDriver driver;
        private IAsyncSession session;

        private const string defaultKey = "n";//默认 代指表等 类似lambda x=> 中的x
        private const string defaultLeftKey = "a";
        private const string defaultRightKey = "b";
        public Neo4jRepository(string dbName, string uri = "neo4j://localhost:7687", string user = "neo4j", string password = "fdbsn0607.")
        {
            driver = GraphDatabase.Driver(uri, AuthTokens.Basic(user, password));
            session = driver.AsyncSession();
        }

        public string Key
        {

            get
            {
                return defaultKey;
            }

        }
        public string LeftKey
        {

            get
            {
                return defaultLeftKey;
            }

        }
        public string RightKey
        {

            get
            {
                return defaultRightKey;
            }

        }


        /// <summary>
        /// 创建 节点名称为n,节点表：lable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="lable"></param>
        /// <param name="key"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<string> CreateSingleNode(string[] label, Dictionary<string, string> inputproperties) 
        {
            try
            {
                string id = "";
                string propertiesStr = "";
                foreach (var v in inputproperties)
                {
                    string propertyBuilder = $"{v.Key}:'{v.Value}',";
                    propertiesStr += propertyBuilder;
                }
                bool isExist = propertiesStr.IndexOf(',', propertiesStr.Length - 1) > 0;
                if (isExist)
                {
                    propertiesStr = propertiesStr.Remove(propertiesStr.Length - 1, 1);
                }
                string labels = string.Join(":", label);
                string graphStr = $"CREATE ({defaultKey}:{labels} {{{propertiesStr}}}) RETURN id({defaultKey})";
                List<IRecord> records = new List<IRecord>();
                await session.WriteTransactionAsync(async txc =>
                {
                    records = await txc.RunAsync(graphStr)
                              .ContinueWith(r => r.Result.ToListAsync())
                              .Unwrap();
                });
                foreach (var item in records)
                {
                    foreach (var item1 in item.Values)
                    {
                        id = item1.Value.ToString();
                    }
                }
                return id;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            
        }
        public async void test()
        {
            string graphStr = $"MATCH ({defaultKey}) RETURN id({defaultKey})";
            List<IRecord> records = new List<IRecord>();
            await session.ReadTransactionAsync(async txc =>
            {
                records = await txc.RunAsync(graphStr)
                          .ContinueWith(r => r.Result.ToListAsync())
                          .Unwrap();
            });
            foreach (var item in records)
            {
                var asd = item.Values;
            }
        }
        /// <summary>
        /// 添加数据关联
        /// </summary>
        /// <param name="labelA">表1</param>
        /// <param name="labelB">表2</param>
        /// <param name="relationName">关系名称</param>
        /// <param name="relationKey">指定关系key</param>
        /// <param name="condition">a.objName = b.objName and a.objId<> b.objId</param>
        /// <returns></returns>
        public async Task<string> MatchNodeByProperty( string relationName, string leftid,string rightid, string properties)
        {
            string id ="";
            string graphStr = $"MATCH ({defaultLeftKey}),({defaultRightKey}) where id({defaultLeftKey})={leftid} and id({defaultRightKey})={rightid}" +
                $" CREATE ({defaultLeftKey})-[r:{relationName}{{{properties}}}]->({defaultRightKey}) return id(r)";
            List<IRecord> records = new List<IRecord>();
            await session.WriteTransactionAsync(async txc =>
            {
                records = await txc.RunAsync(graphStr)
                          .ContinueWith(r => r.Result.ToListAsync())
                          .Unwrap();
            });
            foreach (var item in records)
            {
                foreach (var item1 in item.Values)
                {
                    id = item1.Value.ToString();
                }
            }
            return id;
        }
        /// <summary>
        /// 更新节点数据
        /// </summary>
        /// <param name="label">表名</param>
        /// <param name="setStr"> n.fileNo = 'aaa'</param>
        /// <returns></returns>

        public void UpdateNode(string condition,string removestr, string setStr)
        {
            string graphStr = $"match({defaultKey}) WHERE {condition} REMOVE {removestr} SET {setStr} return {defaultKey}";
            session.RunAsync(graphStr);
            
        }
        /// <summary>
        /// 更新关系属性
        /// </summary>
        public void UpdateRelationProPertie(string condition,string setstr,string removeStr)
        {
            string graphStr = "";
            if (removeStr=="")
            {
                graphStr = $"match(a)-[r]-(b) where id(r)={condition} set {setstr}";
            }
            else
            {
                graphStr = $"match(a)-[r]-(b) where id(r)={condition} remove {removeStr} set {setstr}";
            }
            session.RunAsync(graphStr);
        }
        /// <summary>
        /// 更新关系标签
        /// </summary>
        /// <param name="condition"></param>
        /// <param name="setstr"></param>
        /// <returns></returns>
        public async Task<string> UpdateRelationLabels(string condition, string setstr)
        {
            string id = "";
            string graphStr = $"match(a)-[r]->(b) where {condition}"+
                $" create(a)-[r2:{setstr}]->(b) set r2=r with r,r2 delete r return id(r2)";
            List<IRecord> records = new List<IRecord>();
            await session.WriteTransactionAsync(async txc =>
            {
                records = await txc.RunAsync(graphStr)
                          .ContinueWith(r => r.Result.ToListAsync())
                          .Unwrap();
            });
            foreach (var item in records)
            {
                foreach (var item1 in item.Values)
                {
                    id = item1.Value.ToString();
                }
            }
            return id;
        }
        /// <summary>
        /// 根据标签查询节点列表
        /// </summary>
        /// <param name="condition"></param>
        public async Task<List<string>> LoadNodeByLabel(string condition,int limit)
        {
            string graphStr;
            if (limit == 0 )//limit为全部
            {
                if (condition == null)
                {
                    graphStr = $"MATCH({defaultKey}) RETURN {defaultKey}";
                }
                else
                {
                    graphStr = $"MATCH({defaultKey}:{condition}) RETURN {defaultKey}";
                }
            }
            else
            {
                if (condition == null)
                {
                    graphStr = $"MATCH({defaultKey}) RETURN {defaultKey} LIMIT {limit}";
                }
                else
                {
                    graphStr = $"MATCH({defaultKey}:{condition}) RETURN {defaultKey} LIMIT {limit}";
                }
            }
            
            List<IRecord> records = new List<IRecord>();
            await session.ReadTransactionAsync(async txc =>
            {
                records = await txc.RunAsync(graphStr)
                          .ContinueWith(r => r.Result.ToListAsync())
                          .Unwrap();
            });
            List<string> list = new List<string>();
            var nodeList = records.Select(r => r[0].As<INode>());
            foreach (var r in nodeList)
            {
                Dictionary<string, object> id = new Dictionary<string, object>() {
                    ["id"] = r.Id
                };
                foreach (var item in r.Properties)
                {
                    id.Add(item.Key, item.Value);
                }
                list.Add(JsonConvert.SerializeObject(id));
            }
            return list;
        }
        /// <summary>
        /// 根据属性模糊查询节点列表
        /// </summary>
        /// <param name="condition"></param>
        public async Task<List<string>> LoadNodeByProperties(string condition, string propertie,int limit)
        {
            string graphStr;
            if (limit==0)
            {
                if (condition == null)
                {
                    graphStr = $"MATCH({defaultKey}) RETURN {defaultKey} ";
                }
                else
                {
                    graphStr = $"MATCH({defaultKey}) WHERE {defaultKey}.{propertie} Contains '{condition}' RETURN {defaultKey} ";
                }
            }
            else
            {
                if (condition == null)
                {
                    graphStr = $"MATCH({defaultKey}) RETURN {defaultKey} LIMIT {limit}";
                }
                else
                {
                    graphStr = $"MATCH({defaultKey}) WHERE {defaultKey}.{propertie} Contains '{condition}' RETURN {defaultKey} LIMIT {limit}";
                }
            }
            
            List<IRecord> records = new List<IRecord>();
            await session.ReadTransactionAsync(async txc =>
            {
                records = await txc.RunAsync(graphStr)
                          .ContinueWith(r => r.Result.ToListAsync())
                          .Unwrap();
            });
            List<string> list = new List<string>();
            var nodeList = records.Select(r => r[0].As<INode>());
            foreach (var r in nodeList)
            {
                Dictionary<string, object> id = new Dictionary<string, object>()
                {
                    ["id"] = r.Id
                };
                foreach (var item in r.Properties)
                {
                    id.Add(item.Key, item.Value);
                }
                list.Add(JsonConvert.SerializeObject(id));
            }
            return list;
        }
        /// <summary>
        /// 条件检索结点
        /// </summary>
        /// <param name="labels"></param>
        /// <param name="limit"></param>
        /// <param name="condition"></param>
        /// <returns></returns>
        public async Task<List<string>> ComplexLoad(string labels, int limit,string condition)
        {
            string graphStr;
            if (limit==0)
            {
                if (labels == "")
                {
                    graphStr = $"MATCH({defaultKey}) WHERE {condition} RETURN {defaultKey}";
                }
                else if (condition == "")
                {
                    graphStr = $"MATCH({defaultKey}:{labels}) RETURN {defaultKey}";
                }
                else
                {
                    graphStr = $"MATCH({defaultKey}:{labels}) WHERE {condition} RETURN {defaultKey}";
                }
            }
            else
            {
                if (labels == "")
                {
                    graphStr = $"MATCH({defaultKey}) WHERE {condition} RETURN {defaultKey} LIMIT {limit}";
                }
                else if (condition == "")
                {
                    graphStr = $"MATCH({defaultKey}:{labels}) RETURN {defaultKey} LIMIT {limit}";
                }
                else
                {
                    graphStr = $"MATCH({defaultKey}:{labels}) WHERE {condition} RETURN {defaultKey} LIMIT {limit}";
                }
            }
            
            List<IRecord> records = new List<IRecord>();
            await session.ReadTransactionAsync(async txc =>
            {
                records = await txc.RunAsync(graphStr)
                          .ContinueWith(r => r.Result.ToListAsync())
                          .Unwrap();
            });
            List<string> list = new List<string>();
            var nodeList = records.Select(r => r[0].As<INode>());
            foreach (var r in nodeList)
            {
                Dictionary<string, object> id = new Dictionary<string, object>()
                {
                    ["id"] = r.Id
                };
                foreach (var item in r.Properties)
                {
                    id.Add(item.Key, item.Value);
                }
                list.Add(JsonConvert.SerializeObject(id));
            }
            return list;
        }
        /// <summary>
        /// 根据标签加载关系列表
        /// </summary>
        /// <param name="condition"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        public async Task<Tuple<List<string>, List<string>>> LoadRelations(string condition,int limit)
        {
            string graphStr;
            if (limit==0)
            {
                if (condition == null)
                {
                    graphStr = $"MATCH(a)-[r]->(b) RETURN r,a,b";
                }
                else
                {
                    graphStr = $"MATCH(a)-[r:{condition}]->(b) RETURN r,a,b";
                }
            }
            else
            {
                if (condition == null)
                {
                    graphStr = $"MATCH(a)-[r]->(b) RETURN r,a,b LIMIT {limit}";
                }
                else
                {
                    graphStr = $"MATCH(a)-[r:{condition}]->(b) RETURN r,a,b LIMIT {limit}";
                }
            }
            
            List<IRecord> records = new List<IRecord>();
            await session.ReadTransactionAsync(async txc =>
            {
                records = await txc.RunAsync(graphStr)
                          .ContinueWith(r => r.Result.ToListAsync())
                          .Unwrap();
            });
            List<string> rlist = new List<string>();
            List<string> nodelist = new List<string>();
            var relationList = records.Select(r => r[0].As<IRelationship>());
            var nodeList1 = records.Select(r => r[1].As<INode>()).Distinct();
            var nodeList2 = records.Select(r => r[2].As<INode>()).Distinct();
            foreach (var item in relationList)
            {
                Dictionary<string, object> r = new Dictionary<string, object>()
                {
                    ["id"] = item.Id,
                    ["name"] = item.Type,
                    ["source"] = item.StartNodeId,
                    ["target"] = item.EndNodeId
                };
                rlist.Add(JsonConvert.SerializeObject(r));
            }
            foreach (var r in nodeList1)
            {
                Dictionary<string, object> a = new Dictionary<string, object>()
                {
                    ["id"] = r.Id
                };
                foreach (var item in r.Properties)
                {
                    a.Add(item.Key, item.Value);
                }
                nodelist.Add(JsonConvert.SerializeObject(a));
            }
            foreach (var r in nodeList2)
            {
                Dictionary<string, object> b = new Dictionary<string, object>()
                {
                    ["id"] = r.Id
                };
                foreach (var item in r.Properties)
                {
                    b.Add(item.Key, item.Value);
                }
                nodelist.Add(JsonConvert.SerializeObject(b));
            }
            return new Tuple<List<string>, List<string>>(rlist, nodelist);
        }
        /// <summary>
        /// 根据属性加载关系列表
        /// </summary>
        /// <param name="condition"></param>
        /// <param name="limit"></param>
        /// <param name="propertie"></param>
        /// <returns></returns>
        public async Task<Tuple<List<string>, List<string>>> LoadRelationsByProPerti(string condition, int limit,string propertie)
        {
            string graphStr;
            if (limit==0)
            {
                if (condition == null)
                {
                    graphStr = $"MATCH(a)-[r]->(b) RETURN r,a,b";
                }
                else
                {
                    graphStr = $"MATCH(a)-[r]->(b) WHERE r.{propertie} Contains '{condition}' RETURN r,a,b";
                }
            }
            else
            {
                if (condition == null)
                {
                    graphStr = $"MATCH(a)-[r]->(b) RETURN r,a,b LIMIT {limit}";
                }
                else
                {
                    graphStr = $"MATCH(a)-[r]->(b) WHERE r.{propertie} Contains '{condition}' RETURN r,a,b LIMIT {limit}";
                }
            }
            
            List<IRecord> records = new List<IRecord>();
            await session.ReadTransactionAsync(async txc =>
            {
                records = await txc.RunAsync(graphStr)
                          .ContinueWith(r => r.Result.ToListAsync())
                          .Unwrap();
            });
            List<string> rlist = new List<string>();
            List<string> nodeList = new List<string>();
            var relationList = records.Select(r => r[0].As<IRelationship>());
            var nodeList1 = records.Select(r => r[1].As<INode>()).Distinct();
            var nodeList2 = records.Select(r => r[2].As<INode>()).Distinct();
            foreach (var item in relationList)
            {
                Dictionary<string, object> r = new Dictionary<string, object>()
                {
                    ["id"] = item.Id,
                    ["name"] = item.Type,
                    ["source"] = item.StartNodeId,
                    ["target"] = item.EndNodeId
                };
                rlist.Add(JsonConvert.SerializeObject(r));
            }
            foreach (var r in nodeList1)
            {
                Dictionary<string, object> a = new Dictionary<string, object>()
                {
                    ["id"] = r.Id
                };
                foreach (var item in r.Properties)
                {
                    a.Add(item.Key, item.Value);
                }
                nodeList.Add(JsonConvert.SerializeObject(a));
            }
            foreach (var r in nodeList2)
            {
                Dictionary<string, object> b = new Dictionary<string, object>()
                {
                    ["id"] = r.Id
                };
                foreach (var item in r.Properties)
                {
                    b.Add(item.Key, item.Value);
                }
                nodeList.Add(JsonConvert.SerializeObject(b));
            }
            return new Tuple<List<string>, List<string>>(rlist, nodeList);
        }
        /// <summary>
        /// 条件检索关系
        /// </summary>
        /// <param name="jump"></param>
        /// <param name="idCondition"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        public async Task<Tuple<List<string>, List<string>>> RelationComplexLoad(int jump,string idCondition,int limit,string condition,string type)
        {
            string graphStr="";
            string matchStr = "(n1)";
            string returnStr1 = "n1,";
            string returnStr2 = "";
            if (type==null)
            {
                for (int i = 1; i <= jump; i++)
                {
                    matchStr += $"-[r{i}]->(n{i + 1})";
                    returnStr1 += $"n{i + 1},";
                    returnStr2 += $"r{i},";
                }
            }
            else
            {
                for (int i = 1; i <= jump; i++)
                {
                    matchStr += $"-[r{i}:{type}]->(n{i + 1})";
                    returnStr1 += $"n{i + 1},";
                    returnStr2 += $"r{i},";
                }
            }
            returnStr2 = returnStr2.Remove(returnStr2.Length - 1, 1);//移除最后逗号
            if (limit==0)
            {
                if (idCondition == null && condition == null)
                {
                    graphStr = $"match{matchStr} return {returnStr1}{returnStr2}";
                }
                else if (idCondition == null)
                {
                    graphStr = $"match{matchStr} where {idCondition} return {returnStr1}{returnStr2}";
                }
                else if (condition == null)
                {
                    graphStr = $"match{matchStr} where {idCondition} return {returnStr1}{returnStr2}";
                }
                else
                {
                    graphStr = $"match{matchStr} where {idCondition} and {condition} return {returnStr1}{returnStr2}";
                }
            }
            else
            {
                if (idCondition == null && condition == null)
                {
                    graphStr = $"match{matchStr} return {returnStr1}{returnStr2} limit {limit}";
                }
                else if (idCondition == null)
                {
                    graphStr = $"match{matchStr} where {idCondition} return {returnStr1}{returnStr2} limit {limit}";
                }
                else if (condition == null)
                {
                    graphStr = $"match{matchStr} where {idCondition} return {returnStr1}{returnStr2} limit {limit}";
                }
                else
                {
                    graphStr = $"match{matchStr} where {idCondition} and {condition} return {returnStr1}{returnStr2} limit {limit}";
                }
            }
            
            List<IRecord> records = new List<IRecord>();
            await session.ReadTransactionAsync(async txc =>
            {
                records = await txc.RunAsync(graphStr)
                          .ContinueWith(r => r.Result.ToListAsync())
                          .Unwrap();
            });
            List<string> rlist = new List<string>();
            List<string> nodelist = new List<string>();
            for (int i = 0; i < jump+1 ; i++)
            {
                var nodeList = records.Select(r => r[i].As<INode>()).Distinct();
                foreach (var r in nodeList)
                {
                    Dictionary<string, object> node = new Dictionary<string, object>()
                    {
                        ["id"] = r.Id
                    };
                    foreach (var item in r.Properties)
                    {
                        node.Add(item.Key, item.Value);
                    }
                    nodelist.Add(JsonConvert.SerializeObject(node));
                }
            }
            for (int i = jump+1; i < 2*jump+1; i++)
            {
                var relationList = records.Select(r => r[i].As<IRelationship>()).Distinct();
                foreach (var item in relationList)
                {
                    Dictionary<string, object> r = new Dictionary<string, object>()
                    {
                        ["id"] = item.Id,
                        ["name"] = item.Type,
                        ["source"] = item.StartNodeId,
                        ["target"] = item.EndNodeId
                    };
                    rlist.Add(JsonConvert.SerializeObject(r));
                }
            }
            return new Tuple<List<string>, List<string>>(rlist, nodelist);
        }
        /// <summary>
        /// 查询指定节点标签
        /// </summary>
        /// <typeparam name="T">需要转化的属性</typeparam>
        /// <param name="label">表</param>
        /// <param name="condition">条件</param>
        /// <param name="defaultKey">n 类似 lambda 语法糖中的x等</param>
        /// <returns></returns>
        public async Task<Tuple<List<string>,List<string>>> SelectNodeLabel(string condition)
        {
            List<IRecord> records = new List<IRecord>();
            string graphStr = $"MATCH({defaultKey}) WHERE {condition} return {defaultKey}";
            await session.ReadTransactionAsync(async txc =>
            {
                records = await txc.RunAsync(graphStr)
                          .ContinueWith(r => r.Result.ToListAsync())
                          .Unwrap();
            });
            List<string> labellist = new List<string>();
            List<string> propertilist = new List<string>();
            for (int i = 0; i < records.Count; i++)
            {
                var nodeList = records.Select(r => r[i].As<INode>());
                foreach (var r in nodeList)
                {
                    labellist.Add(JsonConvert.SerializeObject(r.Labels));
                    propertilist.Add(JsonConvert.SerializeObject(r.Properties));
                }
            }
            var nodeList1 = Tuple.Create(labellist, propertilist);
            return nodeList1;
        }
        /// <summary>
        /// 加载所有标签
        /// </summary>
        /// <returns></returns>
        public async Task<List<string>> SelectLabels()
        {
            List<IRecord> records = new List<IRecord>();
            string graphStr = $"MATCH({defaultKey}) RETURN distinct labels({defaultKey})";
            await session.ReadTransactionAsync(async txc =>
            {
                records = await txc.RunAsync(graphStr)
                          .ContinueWith(r => r.Result.ToListAsync())
                          .Unwrap();
            });
            List<string> list = new List<string>();
            foreach (var row in records)
            {
                var columns = row.Values;
                foreach (var item in columns.Values)
                {
                    var test =  JsonUtils.Deserialize<List<string>>(item.ToJson());
                    list.AddRange(test);
                }
            }
            list = list.Distinct().ToList();
            return list;
        }
        /// <summary>
        /// 查看单个关系信息
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        public async Task<Tuple<string,List<string>, List<string>, List<string>>> GetRelation(string condition)
        {
            List<IRecord> records = new List<IRecord>();
            string graphStr = $"MATCH(a)-[r]->(b) where id(r)={condition} RETURN r,a,b";
            await session.ReadTransactionAsync(async txc =>
            {
                records = await txc.RunAsync(graphStr)
                          .ContinueWith(r => r.Result.ToListAsync())
                          .Unwrap();
            });
            string type = "";
            List<string> properti = new List<string>();
            List<string> anodeList = new List<string>();
            List<string> bnodeList = new List<string>();
            var relationList = records.Select(r => r[0].As<IRelationship>());
            var nodeList1 = records.Select(r => r[1].As<INode>()).Distinct();
            var nodeList2 = records.Select(r => r[2].As<INode>()).Distinct();
            foreach (var r in relationList)
            {
                type = JsonConvert.SerializeObject(r.Type);
                properti.Add(JsonConvert.SerializeObject(r.Properties));
                break;
            }
            foreach (var r in nodeList1)
            {
                Dictionary<string, object> a = new Dictionary<string, object>()
                {
                    ["id"] = r.Id
                };
                foreach (var item in r.Properties)
                {
                    a.Add(item.Key, item.Value);
                }
                anodeList.Add(JsonConvert.SerializeObject(a));
            }
            foreach (var r in nodeList2)
            {
                Dictionary<string, object> b = new Dictionary<string, object>()
                {
                    ["id"] = r.Id
                };
                foreach (var item in r.Properties)
                {
                    b.Add(item.Key, item.Value);
                }
                bnodeList.Add(JsonConvert.SerializeObject(b));
            }
            return new Tuple<string, List<string>, List<string>, List<string>>(type, properti, anodeList, bnodeList);
        }
        /// <summary>
        /// 加载关系名
        /// </summary>
        /// <returns></returns>
        public async Task<List<string>> TypeLoad()
        {
            string graphStr = "MATCH()-[r]->() RETURN distinct type(r)";
            List<IRecord> records = new List<IRecord>();
            await session.ReadTransactionAsync(async txc =>
            {
                records = await txc.RunAsync(graphStr)
                          .ContinueWith(r => r.Result.ToListAsync())
                          .Unwrap();
            });
            List<string> list = new List<string>();
            foreach (var row in records)
            {
                var columns = row.Values;
                foreach (var item in columns.Values)
                {
                    list.Add(item.ToString());
                }
            }
            list = list.Distinct().ToList();
            return list;
        }
        /// <summary>
        /// 通过关系查询指定的节点
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="label"></param>
        /// <param name="relationShipName"></param>
        /// <param name="pageCount"></param>
        /// <returns></returns>
        public async Task<Tuple<List<T1>, List<T2>>> SelectNodeByRelationShoip<T1, T2>(
            string leftLabel, string rightLabel, string relationShipName, string condition = "", int pageCount = 10) where T1 : class, new() where T2 : class, new()
        {
            if (!string.IsNullOrWhiteSpace(condition))
            {
                condition = " where " + condition;
            }
            List<IRecord> records = new List<IRecord>();
            string graphStr = $"match ({leftLabel})-[:{relationShipName}]-({rightLabel}) {condition} return {leftLabel},{rightLabel} limit {pageCount}";
            await session.ReadTransactionAsync(async txc =>
            {
                records = await txc.RunAsync(graphStr)
                          .ContinueWith(r => r.Result.ToListAsync())
                          .Unwrap();
            });
            List<T1> leftCollection = new List<T1>();
            List<T2> rigthCollection = new List<T2>();
            var temp = records.Where(x => x.Keys.Where(t => t.Contains(leftLabel)).Any()).Select(r => r[leftLabel].As<INode>());
            var leftNodeList = records.Select(r => r[leftLabel].As<INode>()).Where(x => x.Labels.Contains(leftLabel)).ToList();
            var rigthNodeList = records.Select(r => r[rightLabel].As<INode>()).Where(x => x.Labels.Contains(rightLabel)).ToList(); ;
            foreach (var l in leftNodeList)
            {
                leftCollection.Add(JsonConvert.SerializeObject(l.Properties).ToObject<T1>());
            }

            foreach (var r in rigthNodeList)
            {
                rigthCollection.Add(JsonConvert.SerializeObject(r.Properties).ToObject<T2>());
            }

            return new Tuple<List<T1>, List<T2>>(leftCollection, rigthCollection);

        }

        /// <summary>
        /// 根据id删除关系
        /// </summary>
        /// <param name="condition"></param>
        public void DeleteRelation(string condition)
        {
            string graphStr = $"MATCH()-[r]-() WHERE {condition} DELETE r";
            session.RunAsync(graphStr);
        }

        /// <summary>
        /// 删除节点,如果deleteRelationShip 是false，但删除的有关联数据会异常，如果是关联，必须启动deleteRelationShip为true
        /// </summary>
        /// <param name="label"></param>
        /// <param name="condition"></param>
        /// <param name="defaultKey"></param>
        /// <param name="deleteRelationShip">是否联同关联都删除</param>
        /// <returns></returns>
        public void DeleteNode(string condition, string defaultKey = "n")
        {
            //match(n: UserInfo{ Sex:'女' }) delete n 这种也可以
            string graphStr = $"match({defaultKey}) where {condition} DETACH delete {defaultKey}";
            session.RunAsync(graphStr);
        }
        /// <summary>
        /// 清空数据库
        /// </summary>
        /// <returns></returns>
        public void  DeleteAllNode()
        {
            string graphStr = $"MATCH ({defaultKey}) DETACH DELETE {defaultKey}";
            session.RunAsync(graphStr);
        }
        public async Task Dispose()
        {
            await session.CloseAsync();
            await driver.CloseAsync();
            GC.SuppressFinalize(this);
        }



    }
}
